import ApplicationController from "./application_controller";
import L            from 'leaflet';

export default class extends ApplicationController {

    /**
     *
     * @type {string[]}
     */
    static targets = [
        "search",
        "lat",
        "lng"
    ];

    /**
     *
     */
    connect() {
        const default_lat = this.latTarget.value;
        const default_lng = this.lngTarget.value;
        const default_zoom = this.data.get('zoom');
        const max_zoom = '18';

        let base64icon = '';
        let base64shadow = '';
        let markerIcon = L.icon({
            iconUrl: base64icon,
            iconAnchor: [12, 41],
            iconSize: [25, 41],
            popupAnchor: [1, -34],
            shadowSize: [41, 41],
            shadowUrl: base64shadow
        });

        this.leafletMap = L.map(this.data.get('id'), {
            center: [default_lat, default_lng],
            zoom: default_zoom
        });

        this.leafLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
            maxZoom: max_zoom
        }).addTo(this.leafletMap);

        this.leafletMarker = L.marker([default_lat, default_lng], {
            icon: markerIcon,
            draggable: true,
            autoPan:true,
            autoPanPadding:L.point(100, 100)
        }).addTo(this.leafletMap);

        this.leafletMarker.on('dragend', () => {
            this.updateCoords();
        });

        this.leafletMap.on('click', (e) => {
            this.leafletMarker.setLatLng(e.latlng);
            this.updateCoords();
            this.leafletMap.panTo(e.latlng);
        });

        /**
         * @see https://stackoverflow.com/questions/36246815/data-toggle-tab-does-not-download-leaflet-map/36257493#36257493
         */
        let tabEl = document.querySelector('a[data-bs-toggle="tab"]')
        if(tabEl !== null){
            tabEl.addEventListener('shown.bs.tab',  () => this.leafletMap.invalidateSize())
        }
    }

    /**
     *
     */
    updateCoords() {
        this.latTarget.value = this.leafletMarker.getLatLng().lat;
        this.lngTarget.value  = this.leafletMarker.getLatLng().lng;

        this.latTarget.dispatchEvent(new Event('change'));
        this.lngTarget.dispatchEvent(new Event('change'));
    }

    /**
     *
     */
    search() {
        const results = this.element.querySelector('.marker-results');

        if (this.searchTarget.value.length <= 3) {
            return;
        }

        axios
            .get('https://nominatim.openstreetmap.org/search?format=json&limit=5&q=' + this.searchTarget.value)
            .then(response => {

                let items = [];

                response.data.forEach((val) => {
                    let bb = val.boundingbox;
                    let lat = val.lat;
                    let lng = val.lon;
                    let name = val.display_name;
                    items.push("<li style='cursor:pointer' data-name='" + name + "' data-lat='" + lat + "' data-lng='" + lng + "' data-lat1='" + bb[0] + "' data-lat2='" + bb[1] + "' data-lng1='" + bb[2] + "' data-lng2='" + bb[3] + "' data-type='" + val.osm_type + "' data-action='click->map#chooseAddr'>" + val.display_name + "</li>");
                });

                results.innerHTML = null;

                if (items.length !== 0) {
                    results.innerHTML = "<ul class='my-2'>"+items.join('')+"</ul>";
                    return;
                }

                results.innerHTML = "<small>No results found</small>";
            });

    }

    /**
     *
     * @param e
     */
    chooseAddr(e) {

        const name = e.target.getAttribute("data-name");
        const lat = e.target.getAttribute("data-lat"); //for centering marker
        const lng = e.target.getAttribute("data-lng"); //for centering marker
        const lat1 = e.target.getAttribute("data-lat1");
        const lat2 = e.target.getAttribute("data-lat2");
        const lng1 = e.target.getAttribute("data-lng1");
        const lng2 = e.target.getAttribute("data-lng2");
        const loc1 = new L.LatLng(lat1, lng1);
        const loc2 = new L.LatLng(lat2, lng2);
        const bounds = new L.LatLngBounds(loc1, loc2);

        this.leafletMap.fitBounds(bounds);
        this.leafletMarker.setLatLng([lat, lng]);
        this.updateCoords();
        this.searchTarget.value = name;
    }

}
